//
//  UIDevice+WBHardWare.m
//  WeatherBar
//
//  Created by Bert on 2024/6/25.
//

#import "UIDevice+WBHardWare.h"
#include <sys/socket.h> // Per msqr
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_dl.h>
#import <dlfcn.h>
#import <mach/port.h>
#import <mach/kern_return.h>
#import "SSKeychain.h"
#import <AFNetworking/AFNetworking.h>
#include <ifaddrs.h>
#include <arpa/inet.h>
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
#import <AppTrackingTransparency/AppTrackingTransparency.h>
#import <AdSupport/AdSupport.h>
//#include <net/if.h>
//#import "CommonBaseMacros.h"
#import <objc/message.h>
#import <sys/param.h>
#import <sys/mount.h>
#import <sys/stat.h>
#import <sys/utsname.h>
#import <mach/mach.h>
#import <mach/mach_host.h>
#import <mach/processor_info.h>
#import <CoreTelephony/CTCarrier.h>


#define IOS_CELLULAR    @"pdp_ip0"
#define IOS_WIFI        @"en0"
#define IOS_VPN         @"utun0"
#define IP_ADDR_IPv4    @"ipv4"
#define IP_ADDR_IPv6    @"ipv6"

@implementation UIDevice (WBHardWare)

+ (NSString *)wb_devicePhoneNum {
    return [[NSUserDefaults standardUserDefaults] objectForKey:@"SBFormattedPhoneNumber"];
}

+(NSArray *)wb_carrierNames {
    CTTelephonyNetworkInfo *telephonyNetInfo = [[CTTelephonyNetworkInfo alloc] init];
    NSDictionary<NSString *, CTCarrier *> *carriers = [telephonyNetInfo serviceSubscriberCellularProviders];
    NSMutableArray *carrierNames = [NSMutableArray array];
    if (carriers != nil) {
        for (NSString *key in carriers) {
            CTCarrier *carrier = carriers[key];
            [carrierNames addObject:carrier.carrierName];
            //NSLog(@"isoCountryCode : %@", carrier.isoCountryCode.description);
        }
    }
    return carrierNames;
//    return [carrier carrierName] ? [carrier carrierName] : @"";
}

/// 获取设备型号
/// @param typeSpecifier 类型特点
+ (NSString *)wb_getSysInfoByName:(char *)typeSpecifier
{
    size_t size;
    sysctlbyname(typeSpecifier, NULL, &size, NULL, 0);
    
    char *answer = malloc(size);
    sysctlbyname(typeSpecifier, answer, &size, NULL, 0);
    
    NSString *results = [NSString stringWithCString:answer encoding: NSUTF8StringEncoding];
    
    free(answer);
    return results;
}

/// 获取平台信息
+ (NSString *)wb_platform
{
    return [self wb_getSysInfoByName:"hw.machine"];
}


+ (NSString *)wb_platformString {
    NSString *platform = [self wb_platform];
    if ([platform isEqualToString:@"iPhone1,1"])    return @"iPhone 1G";
    if ([platform isEqualToString:@"iPhone1,2"])    return @"iPhone 3G";
    if ([platform isEqualToString:@"iPhone2,1"])    return @"iPhone 3GS";
    if ([platform isEqualToString:@"iPhone3,1"])    return @"iPhone 4 (GSM)";
    if ([platform isEqualToString:@"iPhone3,3"])    return @"iPhone 4 (CDMA)";
    if ([platform isEqualToString:@"iPhone4,1"])    return @"iPhone 4S";
    if ([platform isEqualToString:@"iPhone5,1"])    return @"iPhone 5 (GSM)";
    if ([platform isEqualToString:@"iPhone5,2"])    return @"iPhone 5 (CDMA)";
    if ([platform isEqualToString:@"iPhone5,3"])    return @"iPhone 5c";
    if ([platform isEqualToString:@"iPhone5,4"])    return @"iPhone 5c";
    if ([platform isEqualToString:@"iPhone6,1"])    return @"iPhone 5s";
    if ([platform isEqualToString:@"iPhone6,2"])    return @"iPhone 5s";
    if ([platform isEqualToString:@"iPhone7,1"])    return @"iPhone 6 Plus";
    if ([platform isEqualToString:@"iPhone7,2"])    return @"iPhone 6";
    if ([platform isEqualToString:@"iPhone8,1"])    return @"iPhone 6s";
    if ([platform isEqualToString:@"iPhone8,2"])    return @"iPhone 6s Plus";
    if ([platform isEqualToString:@"iPhone8,4"])    return @"iPhone SE";
    if ([platform isEqualToString:@"iPhone9,1"])    return @"iPhone 7";
    if ([platform isEqualToString:@"iPhone9,2"])    return @"iPhone 7 Plus";
    if ([platform isEqualToString:@"iPhone9,3"])    return @"iPhone 7";
    if ([platform isEqualToString:@"iPhone9,4"])    return @"iPhone 7 Plus";
    if ([platform isEqualToString:@"iPhone10,1"])   return @"iPhone 8";
    if ([platform isEqualToString:@"iPhone10,4"])   return @"iPhone 8";
    if ([platform isEqualToString:@"iPhone10,2"])   return @"iPhone 8 Plus";
    if ([platform isEqualToString:@"iPhone10,5"])   return @"iPhone 8 Plus";
    if ([platform isEqualToString:@"iPhone10,3"])   return @"iPhone X";
    if ([platform isEqualToString:@"iPhone10,6"])   return @"iPhone X";
    if ([platform isEqualToString:@"iPhone11,2"])   return @"iPhone XS";
    if ([platform isEqualToString:@"iPhone11,4"])   return @"iPhone XS Max";
    if ([platform isEqualToString:@"iPhone11,6"])   return @"iPhone XS Max CN";
    if ([platform isEqualToString:@"iPhone11,8"])   return @"iPhone XR";
    if ([platform isEqualToString:@"iPhone12,1"])   return @"iPhone 11";
    if ([platform isEqualToString:@"iPhone12,3"])   return @"iPhone 11 Pro";
    if ([platform isEqualToString:@"iPhone12,5"])   return @"iPhone 11 Pro Max";
    if ([platform isEqualToString:@"iPhone12,8"])   return @"iPhone SE 2";
    if ([platform isEqualToString:@"iPhone13,1"])   return @"iPhone 12 mini";
    if ([platform isEqualToString:@"iPhone13,2"])   return @"iPhone 12";
    if ([platform isEqualToString:@"iPhone13,3"])   return @"iPhone 12 Pro";
    if ([platform isEqualToString:@"iPhone13,4"])   return @"iPhone 12 Pro Max";
    if ([platform isEqualToString:@"iPhone14,4"])   return @"iPhone 13 mini";
    if ([platform isEqualToString:@"iPhone14,5"])   return @"iPhone 13";
    if ([platform isEqualToString:@"iPhone14,2"])   return @"iPhone 13 Pro";
    if ([platform isEqualToString:@"iPhone14,3"])   return @"iPhone 13 Pro Max";
    if ([platform isEqualToString:@"iPhone14,6"])   return @"iPhone SE 3";
    if ([platform isEqualToString:@"iPhone14,7"])   return @"iPhone 14";
    if ([platform isEqualToString:@"iPhone14,8"])   return @"iPhone 14 Plus";
    if ([platform isEqualToString:@"iPhone15,2"])   return @"iPhone 14 Pro";
    if ([platform isEqualToString:@"iPhone15,3"])   return @"iPhone 14 Pro Max";
    
    
    if ([platform isEqualToString:@"iPod1,1"])      return @"iPod Touch 1G";
    if ([platform isEqualToString:@"iPod2,1"])      return @"iPod Touch 2G";
    if ([platform isEqualToString:@"iPod3,1"])      return @"iPod Touch 3G";
    if ([platform isEqualToString:@"iPod4,1"])      return @"iPod Touch 4G";
    if ([platform isEqualToString:@"iPod5,1"])      return @"iPod Touch 5G";
    if ([platform isEqualToString:@"iPod7,1"])      return @"iPod Touch 6G";
    
    if ([platform isEqualToString:@"iPad1,1"])      return @"iPad";
    if ([platform isEqualToString:@"iPad2,1"])      return @"iPad 2 (WiFi)";
    if ([platform isEqualToString:@"iPad2,2"])      return @"iPad 2 (GSM)";
    if ([platform isEqualToString:@"iPad2,3"])      return @"iPad 2 (CDMA)";
    if ([platform isEqualToString:@"iPad2,4"])      return @"iPad 2 (WiFi)";
    if ([platform isEqualToString:@"iPad2,5"])      return @"iPad Mini (WiFi)";
    if ([platform isEqualToString:@"iPad2,6"])      return @"iPad Mini (GSM)";
    if ([platform isEqualToString:@"iPad2,7"])      return @"iPad Mini (CDMA)";
    if ([platform isEqualToString:@"iPad3,1"])      return @"iPad 3 (WiFi)";
    if ([platform isEqualToString:@"iPad3,2"])      return @"iPad 3 (CDMA)";
    if ([platform isEqualToString:@"iPad3,3"])      return @"iPad 3 (GSM)";
    if ([platform isEqualToString:@"iPad3,4"])      return @"iPad 4 (WiFi)";
    if ([platform isEqualToString:@"iPad3,5"])      return @"iPad 4 (GSM)";
    if ([platform isEqualToString:@"iPad3,6"])      return @"iPad 4 (CDMA)";
    if ([platform isEqualToString:@"iPad4,1"])      return @"iPad Air (WiFi)";
    if ([platform isEqualToString:@"iPad4,2"])      return @"iPad Air (GSM)";
    if ([platform isEqualToString:@"iPad4,3"])      return @"iPad Air (CDMA)";
    if ([platform isEqualToString:@"iPad4,4"])      return @"iPad Mini Retina (WiFi)";
    if ([platform isEqualToString:@"iPad4,5"])      return @"iPad Mini Retina (Cellular)";
    if ([platform isEqualToString:@"iPad4,7"])      return @"iPad Mini 3 (WiFi)";
    if ([platform isEqualToString:@"iPad4,8"])      return @"iPad Mini 3 (Cellular)";
    if ([platform isEqualToString:@"iPad4,9"])      return @"iPad Mini 3 (Cellular)";
    if ([platform isEqualToString:@"iPad5,1"])      return @"iPad Mini 4 (WiFi)";
    if ([platform isEqualToString:@"iPad5,2"])      return @"iPad Mini 4 (Cellular)";
    if ([platform isEqualToString:@"iPad5,3"])      return @"iPad Air 2 (WiFi)";
    if ([platform isEqualToString:@"iPad5,4"])      return @"iPad Air 2 (Cellular)";
    if ([platform isEqualToString:@"iPad6,3"])      return @"iPad Pro 9.7-inch (WiFi)";
    if ([platform isEqualToString:@"iPad6,4"])      return @"iPad Pro 9.7-inch (Cellular)";
    if ([platform isEqualToString:@"iPad6,7"])      return @"iPad Pro 12.9-inch (WiFi)";
    if ([platform isEqualToString:@"iPad6,8"])      return @"iPad Pro 12.9-inch (Cellular)";
    
    if ([platform isEqualToString:@"iPad6,11"])     return @"iPad 5 (WiFi)";
    if ([platform isEqualToString:@"iPad6,12"])     return @"iPad 5 (Cellular)";
    if ([platform isEqualToString:@"iPad7,1"])      return @"iPad Pro 12.9-inch (WiFi)";
    if ([platform isEqualToString:@"iPad7,2"])      return @"iPad Pro 12.9-inch (Cellular)";
    if ([platform isEqualToString:@"iPad7,3"])      return @"iPad Pro 10.5-inch (WiFi)";
    if ([platform isEqualToString:@"iPad7,4"])      return @"iPad Pro 10.5-inch (Cellular)";
    if ([platform isEqualToString:@"iPad7,5"])      return @"iPad 6";
    if ([platform isEqualToString:@"iPad7,6"])      return @"iPad 6";
    if ([platform isEqualToString:@"iPad7,11"])     return @"iPad 7";
    if ([platform isEqualToString:@"iPad7,12"])     return @"iPad 7";
    if ([platform isEqualToString:@"iPad8,1"])      return @"iPad Pro (11-inch) ";
    if ([platform isEqualToString:@"iPad8,2"])      return @"iPad Pro (11-inch) ";
    if ([platform isEqualToString:@"iPad8,3"])      return @"iPad Pro (11-inch) ";
    if ([platform isEqualToString:@"iPad8,4"])      return @"iPad Pro (11-inch) ";
    if ([platform isEqualToString:@"iPad8,5"])      return @"iPad Pro 3 (12.9-inch) ";
    if ([platform isEqualToString:@"iPad8,6"])      return @"iPad Pro 3 (12.9-inch) ";
    if ([platform isEqualToString:@"iPad8,7"])      return @"iPad Pro 3 (12.9-inch) ";
    if ([platform isEqualToString:@"iPad8,8"])      return @"iPad Pro 3 (12.9-inch) ";
    if ([platform isEqualToString:@"iPad8,9"])      return @"iPad Pro 2 (11-inch) ";
    if ([platform isEqualToString:@"iPad8,10"])     return @"iPad Pro 2 (11-inch) ";
    if ([platform isEqualToString:@"iPad8,11"])     return @"iPad Pro 4 (12.9-inch) ";
    if ([platform isEqualToString:@"iPad8,12"])     return @"iPad Pro 4 (12.9-inch) ";
    if ([platform isEqualToString:@"iPad11,1"])     return @"iPad mini 5";
    if ([platform isEqualToString:@"iPad11,2"])     return @"iPad mini 5";
    if ([platform isEqualToString:@"iPad11,3"])     return @"iPad Air 3";
    if ([platform isEqualToString:@"iPad11,4"])     return @"iPad Air 3";
    if ([platform isEqualToString:@"iPad11,6"])     return @"iPad 8";
    if ([platform isEqualToString:@"iPad11,7"])     return @"iPad 8";
    if ([platform isEqualToString:@"iPad12,1"])     return @"iPad 9";
    if ([platform isEqualToString:@"iPad12,2"])     return @"iPad 9";
    if ([platform isEqualToString:@"iPad13,1"])     return @"iPad Air 4";
    if ([platform isEqualToString:@"iPad13,2"])     return @"iPad Air 4";
    if ([platform isEqualToString:@"iPad13,4"])     return @"iPad Pro 4 (11-inch) ";
    if ([platform isEqualToString:@"iPad13,5"])     return @"iPad Pro 4 (11-inch) ";
    if ([platform isEqualToString:@"iPad13,6"])     return @"iPad Pro 4 (11-inch) ";
    if ([platform isEqualToString:@"iPad13,7"])     return @"iPad Pro 4 (11-inch) ";
    if ([platform isEqualToString:@"iPad13,8"])     return @"iPad Pro 5 (12.9-inch) ";
    if ([platform isEqualToString:@"iPad13,9"])     return @"iPad Pro 5 (12.9-inch) ";
    if ([platform isEqualToString:@"iPad13,10"])    return @"iPad Pro 5 (12.9-inch) ";
    if ([platform isEqualToString:@"iPad13,11"])    return @"iPad Pro 5 (12.9-inch) ";
    if ([platform isEqualToString:@"iPad13,18"])    return @"iPad 10";
    if ([platform isEqualToString:@"iPad13,19"])    return @"iPad 10";
    if ([platform isEqualToString:@"iPad14,1"])     return @"iPad mini 6";
    if ([platform isEqualToString:@"iPad14,2"])     return @"iPad mini 6";
    
    if ([platform isEqualToString:@"i386"])         return [UIDevice currentDevice].model;
    if ([platform isEqualToString:@"x86_64"])       return [UIDevice currentDevice].model;
    
    return platform;
}


+ (NSString *)wb_screenInches {
    //px
    CGSize screenSize = [[UIScreen mainScreen] currentMode].size;
    if (CGSizeEqualToSize(screenSize,CGSizeMake(640, 960))) {
        return  @"3.5";//iphone4/4s
    }else if (CGSizeEqualToSize(screenSize,CGSizeMake(640, 1136))) {
        return  @"4.0";//iphone5/5c/5s/SE
    }else if (CGSizeEqualToSize(screenSize,CGSizeMake(750, 1334))) {
        return  @"4.7";//iphone6/6s/7/8
    }else if (CGSizeEqualToSize(screenSize,CGSizeMake(1242, 2208))) {
        return  @"5.5";//iphone6+/6s+/7+/8+
    }else if (CGSizeEqualToSize(screenSize,CGSizeMake(828, 1792))) {
        return  @"6.1";//iphoneXR/11
    }else if (CGSizeEqualToSize(screenSize,CGSizeMake(1125, 2436))) {
        return  @"5.8";//iphoneX/XS/11Pro
    }else if (CGSizeEqualToSize(screenSize,CGSizeMake(1242, 2688))) {
        return  @"6.5";//iphoneXS/MAX 11 Pro Max
    }else if (CGSizeEqualToSize(screenSize,CGSizeMake(1170, 2532)) || CGSizeEqualToSize(screenSize,CGSizeMake(1179, 2556))) {
        return  @"6.1";//iphone12/12Pro
    }else if (CGSizeEqualToSize(screenSize,CGSizeMake(1284, 2778)) || CGSizeEqualToSize(screenSize,CGSizeMake(1290, 2796))) {
        return  @"6.7";//iphone12 Pro Max
    }else if (CGSizeEqualToSize(screenSize,CGSizeMake(1080, 2340))) {
        return  @"5.4";//iphone12 mini
    }else{
        return @"7.9";//未知机型
    }
}



/// 获取IP地址
+ (NSString *)wb_getDeviceIPAdress
{
    struct ifaddrs *interfaces = NULL;
    struct ifaddrs *temp_addr = NULL;
    NSString *wifiAddress = nil;
    NSString *cellAddress = nil;
    
    // retrieve the current interfaces - returns 0 on success
    if(!getifaddrs(&interfaces)) {
        // Loop through linked list of interfaces
        temp_addr = interfaces;
        while(temp_addr != NULL) {
            sa_family_t sa_type = temp_addr->ifa_addr->sa_family;
            if(sa_type == AF_INET || sa_type == AF_INET6) {
                NSString *name = [NSString stringWithUTF8String:temp_addr->ifa_name];
                NSString *addr = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)]; // pdp_ip0
                //NSLog(@"NAME: \"%@\" addr: %@", name, addr); // see for yourself
                
                if([name isEqualToString:@"en0"])
                    // Interface is the wifi connection on the iPhone
                    wifiAddress = addr;
                else
                    if([name isEqualToString:@"pdp_ip0"])
                        // Interface is the cell connection on the iPhone
                        cellAddress = addr;
                
            }
            temp_addr = temp_addr->ifa_next;
        }
        // Free memory
        freeifaddrs(interfaces);
    }
    NSString *addr = wifiAddress ? wifiAddress : cellAddress;
    return addr ? addr : @"0.0.0.0";
}


/// 是否是模拟器
+ (BOOL)wb_isSimulator
{   NSString *hardware = [self wb_platform];
    if ([hardware isEqualToString:@"i386"])
        return YES;
    if ([hardware isEqualToString:@"x86_64"])
        return YES;
    return NO;
}
#pragma mark MAC addy获取mac地址
// Return the local MAC addy
// Courtesy of FreeBSD hackers email list
// Accidentally munged during previous update. Fixed thanks to mlamb.
/// mac地址
+ (NSString *) wb_macaddress
{
    int                 mib[6];
    size_t              len;
    char                *buf;
    unsigned char       *ptr;
    struct if_msghdr    *ifm;
    struct sockaddr_dl  *sdl;
    
    mib[0] = CTL_NET;
    mib[1] = AF_ROUTE;
    mib[2] = 0;
    mib[3] = AF_LINK;
    mib[4] = NET_RT_IFLIST;
    
    if ((mib[5] = if_nametoindex("en0")) == 0) {
        printf("Error: if_nametoindex error\n");
        return NULL;
    }
    
    if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
        printf("Error: sysctl, take 1\n");
        return NULL;
    }
    
    if ((buf = malloc(len)) == NULL) {
        printf("Error: Memory allocation error\n");
        return NULL;
    }
    
    if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
        printf("Error: sysctl, take 2\n");
        free(buf); // Thanks, Remy "Psy" Demerest
        return NULL;
    }
    
    ifm = (struct if_msghdr *)buf;
    sdl = (struct sockaddr_dl *)(ifm + 1);
    ptr = (unsigned char *)LLADDR(sdl);
    NSString *outstring = [NSString stringWithFormat:@"%02X%02X%02X%02X%02X%02X", *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5)];
    
    free(buf);
    return outstring;
}
+ (void)wb_getIdfaCompletion:(void ((^)(NSString * idfa)))completion
{
    if (@available(iOS 14, *)) {
        [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
            if (status == ATTrackingManagerAuthorizationStatusAuthorized) {
                NSString *idfaString = [[ASIdentifierManager sharedManager] advertisingIdentifier].UUIDString;
                if (completion) {
                    completion(idfaString);
                }
                
            }
            else if (completion) {
                if (status == ATTrackingManagerAuthorizationStatusNotDetermined) {
                    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                        [self wb_getIdfaCompletion:completion];
                    });
                }
                completion(@(status).stringValue);
            }
        }];
    }
    else {
        if ([[ASIdentifierManager sharedManager] isAdvertisingTrackingEnabled]) {
            NSString *idfaString = [[ASIdentifierManager sharedManager] advertisingIdentifier].UUIDString;
            if (completion) {
                completion(idfaString);
            }
        }
        else if (completion) {
            completion(@"");
        }
    }
}
+ (NSString *)wb_getIdfaOrIdfv
{
    NSString * idfa;
    if (@available(iOS 14, *)) {
        if ( ATTrackingManager.trackingAuthorizationStatus == ATTrackingManagerAuthorizationStatusAuthorized) {
            idfa =  [[ASIdentifierManager sharedManager] advertisingIdentifier].UUIDString;
        }
    }
    else {
        if (ASIdentifierManager.sharedManager.isAdvertisingTrackingEnabled) {
            idfa =  [[ASIdentifierManager sharedManager] advertisingIdentifier].UUIDString;
        }
    }
    if (beNil(idfa)) {
        idfa  = [[[UIDevice currentDevice] identifierForVendor] UUIDString] ?:@"";
    }
    return idfa;
}


/// 获取设备 UUID，并用把里面的“-”删除
+ (NSString*)wb_getUUID
{
    return [[self wb_createUUID] stringByReplacingOccurrencesOfString:@"-" withString:@""];
}

/// 获取设备 UUID
+ (NSString*)wb_createUUID
{
    CFUUIDRef puuid = CFUUIDCreate( nil );
    CFStringRef uuidString = CFUUIDCreateString( nil, puuid );
    NSString * uuid = (NSString *)CFBridgingRelease(CFStringCreateCopy( NULL, uuidString));
    CFRelease(puuid);
    CFRelease(uuidString);
    
    return uuid;
}

+ (NSString *)wb_getZuid {
    NSString *zuid = [SSKeychain passwordForService:[NSBundle mainBundle].bundleIdentifier account:@""];
    if (beNil(zuid)) {
        NSString *uuid = [NSUUID UUID].UUIDString;
        NSString *zuid = [NSString stringWithFormat:@"%@|123456789001",uuid];
        //把UUID保存到钥匙串
        [SSKeychain setPassword:zuid forService:[NSBundle mainBundle].bundleIdentifier account:@""];
        //立即保存
        [[NSUserDefaults standardUserDefaults] synchronize];
        return zuid;
    }
    return zuid;
}



/// 获取IMEI 设备识别码 (即UUID)
+ (NSString*)wb_getImei
{
    if ([self wb_isGetKeyChain]) {
        return [self wb_getKeyChain];
    } else {
        return [self wb_createKeyChain];
    }
}

/// 是否获取到KeyChain
+ (BOOL)wb_isGetKeyChain
{
    NSString *imei = [self wb_getKeyChain];
    return !beNil(imei);
}
/// 向钥匙串中保存数据
+ (NSString*)wb_createKeyChain
{
    NSString *imei = [[UIDevice currentDevice].systemVersion floatValue]>=7.0 ? [self wb_getUUID]:[self wb_getMAC];
    [SSKeychain setPassword:imei forService:[NSBundle mainBundle].bundleIdentifier account:@""];
    return imei;
}

/// 获取钥匙串中保存数据
+ (NSString*)wb_getKeyChain
{
    static NSString *keyChain = nil;
    if (!keyChain) {
        keyChain = [SSKeychain passwordForService:[NSBundle mainBundle].bundleIdentifier account:@""];
    }
    return keyChain;
}

//mac 地址
+(NSString *)wb_getMAC
{
    return [UIDevice wb_macaddress];
}

/// App状态 是否使用wifi
+ (BOOL)wb_isUsingWifi{
    return [AFNetworkReachabilityManager sharedManager].reachableViaWiFi;
}

/// App状态 是否无网
+ (BOOL)wb_isNoNetConnection
{
    return ![AFNetworkReachabilityManager sharedManager].isReachable;
}

/**
 /// 获取屏幕分辨率
 + (NSString*)getScreenResolution
 {
 CGRect rect = [[UIScreen mainScreen] bounds];
 CGSize size = rect.size;
 CGFloat width = size.width;
 CGFloat height = size.height;
 
 //分辨率
 CGFloat scale_screen = [UIScreen mainScreen].scale;
 NSString* ScreenResolution = [NSString stringWithFormat:@"%.0f,%.0f",width*scale_screen,height*scale_screen];
 
 return ScreenResolution;
 }
 */


/// 网络类型
+ (NSDictionary *)wb_networkTypes{
    
    if (@available(iOS 14.1, *)) {
        return  @{
            CTRadioAccessTechnologyGPRS:@(WBNetworkType2G),
            CTRadioAccessTechnologyEdge:@(WBNetworkType2G),
            CTRadioAccessTechnologyWCDMA:@(WBNetworkType3G),
            CTRadioAccessTechnologyHSDPA:@(WBNetworkType3G),
            CTRadioAccessTechnologyHSUPA:@(WBNetworkType3G),
            CTRadioAccessTechnologyCDMA1x:@(WBNetworkType3G),
            CTRadioAccessTechnologyCDMAEVDORev0:@(WBNetworkType3G),
            CTRadioAccessTechnologyCDMAEVDORevA:@(WBNetworkType3G),
            CTRadioAccessTechnologyCDMAEVDORevB:@(WBNetworkType3G),
            CTRadioAccessTechnologyeHRPD:@(WBNetworkType3G),
            CTRadioAccessTechnologyLTE:@(WBNetworkType4G),
            CTRadioAccessTechnologyNRNSA:@(WBNetworkType5G),
            CTRadioAccessTechnologyNR:@(WBNetworkType5G),
        };
    }else
    {
        return  @{
            CTRadioAccessTechnologyGPRS:@(WBNetworkType2G),
            CTRadioAccessTechnologyEdge:@(WBNetworkType2G),
            CTRadioAccessTechnologyWCDMA:@(WBNetworkType3G),
            CTRadioAccessTechnologyHSDPA:@(WBNetworkType3G),
            CTRadioAccessTechnologyHSUPA:@(WBNetworkType3G),
            CTRadioAccessTechnologyCDMA1x:@(WBNetworkType3G),
            CTRadioAccessTechnologyCDMAEVDORev0:@(WBNetworkType3G),
            CTRadioAccessTechnologyCDMAEVDORevA:@(WBNetworkType3G),
            CTRadioAccessTechnologyCDMAEVDORevB:@(WBNetworkType3G),
            CTRadioAccessTechnologyeHRPD:@(WBNetworkType3G),
            CTRadioAccessTechnologyLTE:@(WBNetworkType4G),
        };
    }
    
}


/// 当前网络类型
+ (WBNetworkType)currentNetWorkType{
    AFNetworkReachabilityStatus status =  [AFNetworkReachabilityManager sharedManager].networkReachabilityStatus;
    switch (status) {
        case AFNetworkReachabilityStatusReachableViaWiFi:
            return WBNetworkTypeWifi;
        case AFNetworkReachabilityStatusReachableViaWWAN:
        {
            CTTelephonyNetworkInfo *telephonyInfo = [[CTTelephonyNetworkInfo alloc] init];
            NSNumber *number = [[self wb_networkTypes] objectForKey:telephonyInfo.currentRadioAccessTechnology];
            return number ? (WBNetworkType)[number integerValue] : WBNetworkTypeWwan;
        }
        default:
            return WBNetworkTypeUnknown;
    }
}

+ (NSString *)wb_getNetworkReachabilityStatus{
    
    NSInteger currentNetWorkType = [self currentNetWorkType];
    NSString *currentNetWorkState = @"";
    switch (currentNetWorkType) {
        case WBNetworkTypeUnknown:
            currentNetWorkState = @"未知";
            break;
        case WBNetworkTypeWifi:
            currentNetWorkState = @"wifi";
            break;
        case WBNetworkType2G:
            currentNetWorkState = @"2g";
            break;
        case WBNetworkType3G:
            currentNetWorkState = @"3g";
            break;
        case WBNetworkType4G:
            currentNetWorkState = @"4g";
            break;
            
        default:
            currentNetWorkState = @"5g";
            break;
    }
    return currentNetWorkState;
}



#pragma mark - sysctl utils

+ (NSUInteger)wb_getSysInfo:(uint)typeSpecifier
{
    size_t size = sizeof(int);
    int result;
    int mib[2] = {CTL_HW, typeSpecifier};
    sysctl(mib, 2, &result, &size, NULL, 0);
    return (NSUInteger)result;
}

#pragma mark - memory information
+ (NSUInteger)wb_cpuFrequency {
    return [self wb_getSysInfo:HW_CPU_FREQ];
}

+ (NSUInteger)wb_busFrequency {
    return [self wb_getSysInfo:HW_BUS_FREQ];
}

+ (NSUInteger)wb_ramSize {
    return [self wb_getSysInfo:HW_MEMSIZE];
}

+ (NSUInteger)wb_cpuNumber {
    return [self wb_getSysInfo:HW_NCPU];
}


+ (NSUInteger)wb_totalMemoryBytes
{
    return [self wb_getSysInfo:HW_PHYSMEM];
}

+ (NSUInteger)wb_freeMemoryBytes
{
    mach_port_t host_port = mach_host_self();
    mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);
    vm_size_t pagesize;
    vm_statistics_data_t vm_stat;
    
    host_page_size(host_port, &pagesize);
    if (host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size) != KERN_SUCCESS) {
        return 0;
    }
    unsigned long mem_free = vm_stat.free_count * pagesize;
    return mem_free;
}

#pragma mark - disk information

+ (long long)wb_freeDiskSpaceBytes
{
    struct statfs buf;
    long long freespace;
    freespace = 0;
    if ( statfs("/private/var", &buf) >= 0 ) {
        freespace = (long long)buf.f_bsize * buf.f_bfree;
    }
    return freespace;
}

+ (long long)wb_totalDiskSpaceBytes
{
    struct statfs buf;
    long long totalspace;
    totalspace = 0;
    if ( statfs("/private/var", &buf) >= 0 ) {
        totalspace = (long long)buf.f_bsize * buf.f_blocks;
    }
    return totalspace;
}


+ (nullable UIView *)wb_getStatusBar {
    UIView *_statusBar = nil;
    if (@available(iOS 13.0, *)) {
        UIStatusBarManager *statusBarManager = [UIApplication sharedApplication].keyWindow.windowScene.statusBarManager;
        SEL aSelector = NSSelectorFromString(@"createLocalStatusBar");
        if ([statusBarManager respondsToSelector:aSelector]) {
            UIView *_localView = ((id(*)(id, SEL))objc_msgSend)(statusBarManager, aSelector);
            _statusBar = [_localView valueForKeyPath:@"statusBar"];
        }
    } else {
        UIApplication *app = [UIApplication sharedApplication];
        _statusBar = [app valueForKeyPath:@"statusBar"];
    }
    return _statusBar;
}

+ (NSString *)wb_getNetworkTypes:(UIView *)statusBar {
    NSString __block *network = @"";
    dispatch_async(dispatch_get_main_queue(), ^{
        
        if ([UIDevice wb_safeTop]>24) {
            //        刘海屏
            id statusBarView = [statusBar valueForKeyPath:@"statusBar"];
            UIView *foregroundView = [statusBarView valueForKeyPath:@"foregroundView"];
            NSArray *subviews = [[foregroundView subviews][2] subviews];
            
            if (subviews.count == 0) {
                //            iOS 12
                id currentData = [statusBarView valueForKeyPath:@"currentData"];
                id wifiEntry = [currentData valueForKey:@"wifiEntry"];
                if ([[wifiEntry valueForKey:@"_enabled"] boolValue]) {
                    network = @"WIFI";
                }else {
                    //                卡1:
                    id cellularEntry = [currentData valueForKey:@"cellularEntry"];
                    //                卡2:
                    id secondaryCellularEntry = [currentData valueForKey:@"secondaryCellularEntry"];
                    
                    if (([[cellularEntry valueForKey:@"_enabled"] boolValue]|[[secondaryCellularEntry valueForKey:@"_enabled"] boolValue]) == NO) {
                        //                    无卡情况
                        network = @"NONE";
                    }else {
                        //                    判断卡1还是卡2
                        BOOL isCardOne = [[cellularEntry valueForKey:@"_enabled"] boolValue];
                        int networkType = isCardOne ? [[cellularEntry valueForKey:@"type"] intValue] : [[secondaryCellularEntry valueForKey:@"type"] intValue];
                        switch (networkType) {
                            case 0://无服务
                                network = [NSString stringWithFormat:@"%@-%@", isCardOne ? @"Card 1" : @"Card 2", @"NONE"];
                                break;
                            case 3:
                                network = [NSString stringWithFormat:@"%@-%@", isCardOne ? @"Card 1" : @"Card 2", @"2G/E"];
                                break;
                            case 4:
                                network = [NSString stringWithFormat:@"%@-%@", isCardOne ? @"Card 1" : @"Card 2", @"3G"];
                                break;
                            case 5:
                                network = [NSString stringWithFormat:@"%@-%@", isCardOne ? @"Card 1" : @"Card 2", @"4G"];
                                break;
                            default:
                                break;
                        }
                        
                    }
                }
                
            }else {
                
                for (id subview in subviews) {
                    if ([subview isKindOfClass:NSClassFromString(@"_UIStatusBarWifiSignalView")]) {
                        network = @"WIFI";
                    }else if ([subview isKindOfClass:NSClassFromString(@"_UIStatusBarStringView")]) {
                        network = [subview valueForKeyPath:@"originalText"];
                    }
                }
            }
            
        }else {
            //        非刘海屏
            UIView *foregroundView = [statusBar valueForKeyPath:@"foregroundView"];
            NSArray *subviews = [foregroundView subviews];
            
            for (id subview in subviews) {
                if ([subview isKindOfClass:NSClassFromString(@"UIStatusBarDataNetworkItemView")]) {
                    int networkType = [[subview valueForKeyPath:@"dataNetworkType"] intValue];
                    switch (networkType) {
                        case 0:
                            network = @"NONE";
                            break;
                        case 1:
                            network = @"2G";
                            break;
                        case 2:
                            network = @"3G";
                            break;
                        case 3:
                            network = @"4G";
                            break;
                        case 5:
                            network = @"WIFI";
                            break;
                        default:
                            break;
                    }
                }
            }
        }
    });

    if ([network isEqualToString:@""]) {
        network = @"NO DISPLAY";
    }
    return network;
}

+ (NSString *)wb_getNetworkTypesForiOS13:(UIView *)_statusBar {
    NSString *network = @"";
    if (_statusBar) {
        // _UIStatusBarDataCellularEntry
        id currentData = [[_statusBar valueForKeyPath:@"_statusBar"] valueForKeyPath:@"currentData"];
        id _wifiEntry = [currentData valueForKeyPath:@"wifiEntry"];
        id _cellularEntry = [currentData valueForKeyPath:@"cellularEntry"];
        if (_wifiEntry && [[_wifiEntry valueForKeyPath:@"isEnabled"] boolValue]) {
            network = @"WIFI"; // If wifiEntry is enabled, is WiFi.
        } else if (_cellularEntry && [[_cellularEntry valueForKeyPath:@"isEnabled"] boolValue]) {
            NSNumber *type = [_cellularEntry valueForKeyPath:@"type"];
            if (type) {
                switch (type.integerValue) {
                    case 5:
                        network = @"4G";
                        break;
                    case 4:
                        network = @"3G";
                        break;
                    case 0: // Return 0 when no sim card.
                        network = @"NONE";
                    default:
                        network = @"WIFI";
                        break;
                }
            }
        }
    }
    return network;
}

+ (NSString *)wb_getNetworkType
{
    __block id statusBar = nil;
    if ([NSThread.currentThread isMainThread]) {
        statusBar = [self wb_getStatusBar];
    } else {
        dispatch_sync(dispatch_get_main_queue(), ^{
            statusBar = [self wb_getStatusBar];
        });
    }
    
    if (@available(iOS 13.0, *)) {
        return [self wb_getNetworkTypesForiOS13:statusBar];
    } else {
        return [self wb_getNetworkTypes:statusBar];
    }
}

@end
